package com.lp.serialportlp

import android.serialport.SerialPort
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.lang.Thread.sleep

/**
 * 串口管理类，负责串口的打开、关闭和数据收发
 */
class SerialPortManager private constructor() {
  private var serialPort: SerialPort? = null
  private var inputStream: InputStream? = null
  private var outputStream: OutputStream? = null
  private var readThread: ReadThread? = null

  companion object {
    private const val TAG = "SerialPortManager"
    private var instance: SerialPortManager? = null

    fun getInstance(): SerialPortManager {
      if (instance == null) {
        instance = SerialPortManager()
      }
      return instance!!
    }
  }

  /**
   * 打开串口
   * @param devicePath 串口设备路径，如 "/dev/ttyS1"
   * @param baudrate 波特率，如 9600
   * @return 是否成功打开
   */
  fun open(devicePath: String, baudrate: Int): Boolean {
    return try {
      serialPort = SerialPort(File(devicePath), baudrate)
      inputStream = serialPort?.inputStream
      outputStream = serialPort?.outputStream

      readThread = ReadThread()
      readThread!!.start()
      true
    } catch (e: Exception) {
      MyLog.e(TAG, "打开串口失败: ${e.message}")
      false
    }
  }

  /**
   * 关闭串口
   */
  fun close() {
    try {
      serialPort?.close()
      serialPort = null
      inputStream = null
      outputStream = null
    } catch (e: Exception) {
      MyLog.e(TAG, "关闭串口失败: ${e.message}")
    }
  }

  /**
   * 发送数据
   * @param data 要发送的数据字节数组
   * @return 是否成功发送
   */
  private fun sendData(data: ByteArray): Boolean {
    return try {
      outputStream?.write(data)
      outputStream?.flush()

      MyLog.e(TAG, "send发送: ${CRCUtils.bytesToHex(data)}")
      true
    } catch (e: IOException) {
      MyLog.e(TAG, "发送数据失败: ${e.message}")
      false
    }
  }


  /**
   * 计算CRC16校验码
   * @param data 要计算的数据
   * @return CRC16校验码
   */
  fun calculateCRC16(data: ByteArray): Int {
    var crc = 0xFFFF
    for (b in data) {
      crc = crc xor (b.toInt() and 0xFF)
      for (i in 0 until 8) {
        if (crc and 0x0001 != 0) {
          crc = crc shr 1
          crc = crc xor 0xA001
        } else {
          crc = crc shr 1
        }
      }
    }
    return crc
  }

  /**
   * 验证CRC16校验码
   * @param data 包含CRC的数据帧
   * @return 校验是否通过
   */
  fun verifyCRC16(data: ByteArray): Boolean {
    if (data.size < 2) return false

    val receivedCRC = ((data[data.size - 1].toInt() and 0xFF) shl 8) or
      (data[data.size - 2].toInt() and 0xFF)
    val calculatedCRC = calculateCRC16(data.copyOf(data.size - 2))

    return receivedCRC == calculatedCRC
  }

  /**
   * 执行Modbus事务（发送请求并接收响应）
   * @param request 请求数据
   * @param timeout 超时时间（毫秒）
   * @return 响应数据，失败返回null
   */
  var requestData: ByteArray? = null
  fun executeModbusTransaction(request: ByteArray, timeout: Long = 1000): ByteArray? {
    // 清空之前的响应数据
    requestData = null

    // 发送请求
    if (!sendData(request)) {
      return null
    }

    // 等待响应
    val startTime = System.currentTimeMillis()
    var elapsedTime = 0L

    while (elapsedTime < timeout) {
      // 检查是否有响应数据
      if (requestData != null) {
        // 验证CRC校验
        if (verifyCRC16(requestData!!)) {
          return requestData
        } else {
          // CRC校验失败，继续等待可能还有后续数据
          sleep(10)
        }
      } else {
        // 没有数据时短暂等待
        sleep(10)
      }

      elapsedTime = System.currentTimeMillis() - startTime
    }

    // 超时或CRC校验失败
    return if (requestData != null && verifyCRC16(requestData!!)) {
      requestData
    } else {
      null
    }
  }

  /**
   * 数据读取线程 - 修改为持续监听并存储数据
   */
  private inner class ReadThread : Thread() {
    override fun run() {
      super.run()
      val buffer = ByteArray(1024)

      while (!isInterrupted) {
        try {
          // 检查是否有可用数据
          if (inputStream!!.available() > 0) {
            // 读取数据
            val size = inputStream!!.read(buffer)

            if (size > 0) {
              val receivedData = ByteArray(size)
              System.arraycopy(buffer, 0, receivedData, 0, size)

              // 更新响应数据
              requestData = receivedData

              OnCVDCallBackUitl.doCallBackRequestData(CRCUtils.bytesToHex(receivedData))

              // 记录接收到的数据
              MyLog.e(TAG, "接收: ${CRCUtils.bytesToHex(receivedData)}")
            }
          } else {
            // 没有数据时短暂休眠，避免CPU占用过高
            sleep(10)
          }
        } catch (e: IOException) {
          MyLog.d(TAG, "读取数据时发生IO异常${e.message}")
        } catch (e: InterruptedException) {
          MyLog.d(TAG, "读取线程被中断${e.message}")
          break
        } catch (e: Exception) {
          MyLog.d(TAG, "读取数据时发生未知异常${e.message}")
        }
      }
    }
  }
}
